// 微服务端到端测试用例
import { microservicesE2EConfig, microservicesE2EUtils } from '../support/microservices-e2e-config.js'
import { testDataManager } from '../support/test-data-manager.js'

describe('微服务端到端测试', () => {
  let testResults = []
  let testScenario = null

  before(() => {
    // 测试前检查所有服务健康状态
    cy.log('开始微服务端到端测试')
  })

  after(() => {
    // 生成测试报告
    const report = microservicesE2EUtils.generateE2EReport(testResults)
    cy.log('端到端测试报告:', report)
    
    // 清理测试数据
    testDataManager.cleanupTestData()
  })

  describe('服务健康检查', () => {
    it('应该检查所有微服务健康状态', () => {
      cy.wrap(null).then(async () => {
        const healthResults = await microservicesE2EUtils.checkAllServicesHealth()
        
        // 验证所有服务都健康
        Object.entries(healthResults).forEach(([serviceName, health]) => {
          expect(health.healthy, `${serviceName} 服务应该健康`).to.be.true
        })
        
        testResults.push({
          testName: '服务健康检查',
          success: Object.values(healthResults).every(h => h.healthy),
          serviceHealth: healthResults
        })
      })
    })

    it('应该验证服务发现功能', () => {
      cy.wrap(null).then(async () => {
        const discoveryResult = await microservicesE2EUtils.verifyServiceDiscovery()
        
        expect(discoveryResult.success, '服务发现应该正常工作').to.be.true
        expect(discoveryResult.consulHealthy, 'Consul应该健康').to.be.true
        
        testResults.push({
          testName: '服务发现验证',
          success: discoveryResult.success,
          services: discoveryResult.services
        })
      })
    })
  })

  describe('用户认证端到端测试', () => {
    it('应该完成完整的用户注册登录流程', () => {
      // 创建测试用户
      testDataManager.createTestUser({
        account: `e2e_user_${Date.now()}`,
        password: 'Test@123',
        name: '端到端测试用户',
        role: 'Student'
      }).then((userResult) => {
        expect(userResult.success, '用户创建应该成功').to.be.true
        
        // 用户登录
        return testDataManager.getUserToken(userResult.user.account, userResult.user.password)
      }).then((tokenResult) => {
        expect(tokenResult.success, '用户登录应该成功').to.be.true
        expect(tokenResult.token, '应该返回有效的令牌').to.not.be.empty
        
        testResults.push({
          testName: '用户认证端到端测试',
          success: true,
          scenario: 'userAuthentication'
        })
      })
    })
  })

  describe('课程管理端到端测试', () => {
    it('应该完成完整的课程管理流程', () => {
      let teacherToken = null
      let createdCourse = null
      
      // 1. 创建教师用户并登录
      testDataManager.createTestUser({
        role: 'Teacher',
        account: `e2e_teacher_${Date.now()}`,
        name: '端到端测试教师'
      }).then((teacherResult) => {
        expect(teacherResult.success, '教师创建应该成功').to.be.true
        
        return testDataManager.getUserToken(teacherResult.user.account, teacherResult.user.password)
      }).then((tokenResult) => {
        expect(tokenResult.success, '教师登录应该成功').to.be.true
        teacherToken = tokenResult.token
        
        // 2. 创建课程
        return testDataManager.createTestCourse({
          courseName: `E2E测试课程_${Date.now()}`,
          description: '端到端测试课程'
        }, teacherToken)
      }).then((courseResult) => {
        expect(courseResult.success, '课程创建应该成功').to.be.true
        createdCourse = courseResult.course
        
        // 3. 创建学生用户
        return testDataManager.createTestUser({
          role: 'Student',
          account: `e2e_student_${Date.now()}`,
          name: '端到端测试学生'
        })
      }).then((studentResult) => {
        expect(studentResult.success, '学生创建应该成功').to.be.true
        
        // 4. 学生加入课程（通过API网关）
        return cy.request({
          method: 'POST',
          url: `${microservicesE2EConfig.healthChecks.apiGateway.url.replace('/actuator/health', '')}/api/courses/${createdCourse.courseId}/join`,
          body: { userId: studentResult.user.id },
          failOnStatusCode: false
        })
      }).then((joinResponse) => {
        expect(joinResponse.status, '学生加入课程应该成功').to.be.oneOf([200, 201])
        
        testResults.push({
          testName: '课程管理端到端测试',
          success: true,
          scenario: 'courseManagement'
        })
      })
    })
  })

  describe('练习管理端到端测试', () => {
    it('应该完成完整的练习管理流程', () => {
      let teacherToken = null
      let studentToken = null
      let createdExercise = null
      
      // 1. 创建教师和学生
      Promise.all([
        testDataManager.createTestUser({ role: 'Teacher' }),
        testDataManager.createTestUser({ role: 'Student' })
      ]).then(([teacherResult, studentResult]) => {
        expect(teacherResult.success, '教师创建应该成功').to.be.true
        expect(studentResult.success, '学生创建应该成功').to.be.true
        
        return Promise.all([
          testDataManager.getUserToken(teacherResult.user.account, teacherResult.user.password),
          testDataManager.getUserToken(studentResult.user.account, studentResult.user.password)
        ])
      }).then(([teacherTokenResult, studentTokenResult]) => {
        expect(teacherTokenResult.success, '教师登录应该成功').to.be.true
        expect(studentTokenResult.success, '学生登录应该成功').to.be.true
        
        teacherToken = teacherTokenResult.token
        studentToken = studentTokenResult.token
        
        // 2. 创建练习
        return testDataManager.createTestExercise({
          name: `E2E测试练习_${Date.now()}`,
          description: '端到端测试练习'
        }, null, teacherToken)
      }).then((exerciseResult) => {
        expect(exerciseResult.success, '练习创建应该成功').to.be.true
        createdExercise = exerciseResult.exercise
        
        // 3. 学生提交答案
        return cy.request({
          method: 'POST',
          url: `${microservicesE2EConfig.healthChecks.apiGateway.url.replace('/actuator/health', '')}/api/exercises/${createdExercise.id}/submit`,
          body: {
            userId: studentToken,
            answers: [
              { questionId: 1, answer: 'A' },
              { questionId: 2, answer: ['A', 'B'] },
              { questionId: 3, answer: '这是学生的答案' }
            ]
          },
          headers: { 'Authorization': `Bearer ${studentToken}` },
          failOnStatusCode: false
        })
      }).then((submitResponse) => {
        expect(submitResponse.status, '答案提交应该成功').to.be.oneOf([200, 201])
        
        testResults.push({
          testName: '练习管理端到端测试',
          success: true,
          scenario: 'exerciseManagement'
        })
      })
    })
  })

  describe('学习进度端到端测试', () => {
    it('应该完成完整的学习进度跟踪流程', () => {
      let studentToken = null
      let courseId = null
      
      // 1. 创建学生用户
      testDataManager.createTestUser({
        role: 'Student',
        account: `e2e_progress_student_${Date.now()}`
      }).then((studentResult) => {
        expect(studentResult.success, '学生创建应该成功').to.be.true
        
        return testDataManager.getUserToken(studentResult.user.account, studentResult.user.password)
      }).then((tokenResult) => {
        expect(tokenResult.success, '学生登录应该成功').to.be.true
        studentToken = tokenResult.token
        
        // 2. 更新学习进度
        return cy.request({
          method: 'POST',
          url: `${microservicesE2EConfig.healthChecks.progressService.url.replace('/actuator/health', '')}/api/progress/update`,
          body: {
            userId: studentToken,
            courseId: 'TEST_COURSE_001',
            progress: 50,
            lastActivity: new Date().toISOString()
          },
          headers: { 'Authorization': `Bearer ${studentToken}` },
          failOnStatusCode: false
        })
      }).then((progressResponse) => {
        expect(progressResponse.status, '进度更新应该成功').to.be.oneOf([200, 201])
        
        // 3. 查看学习记录
        return cy.request({
          method: 'GET',
          url: `${microservicesE2EConfig.healthChecks.progressService.url.replace('/actuator/health', '')}/api/progress/learning/${studentToken}/TEST_COURSE_001`,
          headers: { 'Authorization': `Bearer ${studentToken}` },
          failOnStatusCode: false
        })
      }).then((recordsResponse) => {
        expect(recordsResponse.status, '学习记录查询应该成功').to.be.oneOf([200, 201])
        
        testResults.push({
          testName: '学习进度端到端测试',
          success: true,
          scenario: 'learningProgress'
        })
      })
    })
  })

  describe('跨服务数据一致性测试', () => {
    it('应该验证跨服务数据一致性', () => {
      let userId = null
      let courseId = null
      
      // 1. 创建用户和课程
      testDataManager.createTestUser({
        account: `e2e_consistency_user_${Date.now()}`
      }).then((userResult) => {
        expect(userResult.success, '用户创建应该成功').to.be.true
        userId = userResult.user.id
        
        return testDataManager.createTestCourse({
          courseId: `E2E_CONSISTENCY_${Date.now()}`,
          courseName: '数据一致性测试课程'
        })
      }).then((courseResult) => {
        expect(courseResult.success, '课程创建应该成功').to.be.true
        courseId = courseResult.course.courseId
        
        // 2. 验证数据一致性
        return microservicesE2EUtils.verifyDataConsistency(userId, courseId)
      }).then((consistencyChecks) => {
        // 验证所有服务的数据一致性
        expect(consistencyChecks.userService, '用户服务数据应该一致').to.be.true
        expect(consistencyChecks.courseService, '课程服务数据应该一致').to.be.true
        expect(consistencyChecks.progressService, '进度服务数据应该一致').to.be.true
        
        testResults.push({
          testName: '跨服务数据一致性测试',
          success: Object.values(consistencyChecks).every(check => check),
          scenario: 'dataConsistency',
          consistencyChecks
        })
      })
    })
  })

  describe('API网关路由测试', () => {
    it('应该验证API网关正确路由到各个微服务', () => {
      const testRoutes = [
        { path: '/api/users/login', method: 'POST', service: 'userService' },
        { path: '/api/courses', method: 'GET', service: 'courseService' },
        { path: '/api/exercises', method: 'GET', service: 'exerciseService' },
        { path: '/api/progress/statistics', method: 'GET', service: 'progressService' }
      ]
      
      const routeResults = []
      
      testRoutes.forEach(route => {
        cy.request({
          method: route.method,
          url: `${microservicesE2EConfig.healthChecks.apiGateway.url.replace('/actuator/health', '')}${route.path}`,
          failOnStatusCode: false
        }).then((response) => {
          // 验证路由是否正常工作（不一定是200，但应该有响应）
          expect(response.status, `${route.path} 路由应该正常工作`).to.not.be.undefined
          
          routeResults.push({
            route: route.path,
            service: route.service,
            status: response.status,
            success: response.status < 500 // 5xx错误表示服务不可用
          })
        })
      })
      
      cy.wrap(routeResults).then((results) => {
        const allRoutesWorking = results.every(r => r.success)
        expect(allRoutesWorking, '所有API网关路由应该正常工作').to.be.true
        
        testResults.push({
          testName: 'API网关路由测试',
          success: allRoutesWorking,
          routeResults: results
        })
      })
    })
  })

  describe('微服务通信测试', () => {
    it('应该验证微服务间通信正常', () => {
      // 测试微服务间的依赖关系
      const communicationTests = [
        {
          name: '用户服务到课程服务',
          from: 'userService',
          to: 'courseService',
          test: () => {
            // 创建用户，然后创建课程（需要用户信息）
            return testDataManager.createTestUser().then((userResult) => {
              return testDataManager.createTestCourse({
                teacherId: userResult.user.id
              })
            })
          }
        },
        {
          name: '课程服务到练习服务',
          from: 'courseService', 
          to: 'exerciseService',
          test: () => {
            // 创建课程，然后创建练习（需要课程信息）
            return testDataManager.createTestCourse().then((courseResult) => {
              return testDataManager.createTestExercise({
                courseId: courseResult.course.courseId
              })
            })
          }
        }
      ]
      
      const communicationResults = []
      
      communicationTests.forEach(test => {
        test.test().then((result) => {
          communicationResults.push({
            name: test.name,
            from: test.from,
            to: test.to,
            success: result.success
          })
        })
      })
      
      cy.wrap(communicationResults).then((results) => {
        const allCommunicationsWorking = results.every(r => r.success)
        expect(allCommunicationsWorking, '所有微服务间通信应该正常').to.be.true
        
        testResults.push({
          testName: '微服务通信测试',
          success: allCommunicationsWorking,
          communicationResults: results
        })
      })
    })
  })
})
